/*
 * @Author       : YeRuoyu
 * @Date         : 2023-06-01 14:33:48
 * @LastEditors  : YeRuoyu ruoyu722@qq.com
 * @LastEditTime : 2023-06-02 14:52:15
 * @FilePath     : \list.c
 * @Description  : 一个通用链表库
 * Copyright (c) 2023 by YeRuoyu ruoyu722@qq.com, All Rights Reserved.
 */
#include "list.h"

/**
 * @brief    初始化链表
 * @param    (List_t) *pxList : 需要初始化的链表指针
 * @return   (void)
 */
void vListInitialise(List_t *const pxList)
{
	/* 初始化链表尾(此节点做标记用) */
	pxList->pxIndex = (ListItem_t *)&(pxList->xListEnd);

	/* 空链表的下一个指针和前一个指针指向自己 */
	pxList->xListEnd.pxNext = (ListItem_t *)&(pxList->xListEnd);
	pxList->xListEnd.pxPrevious = (ListItem_t *)&(pxList->xListEnd);

	/* 链表节点数初始化为0 */
	pxList->uxNumberOfItems = (UBaseType_t)0U;
}

/**
 * @brief    插入新节点到链表尾部
 * @param    (List_t) *pxList : 待插入的链表
 * @param    (ListItem_t) *pxNewListItem : 新节点
 * @return   (void)
 */
void vListInsertEnd(List_t *const pxList, ListItem_t *const pxNewListItem)
{
	ListItem_t *const pxIndex = pxList->pxIndex;

	pxNewListItem->pxNext = pxIndex;
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;

	pxIndex->pxPrevious->pxNext = pxNewListItem;
	pxIndex->pxPrevious = pxNewListItem;

	/* 记住项目在哪个链表中。 */
	pxNewListItem->pxList = pxList;

	(pxList->uxNumberOfItems)++;
}

/**
 * @brief   从链表中移除一个节点
 * @param   (ListItem_t *) pxItemToRemove: 待移除的节点
 * @return  返回链表中剩余节点数量
 */
UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove)
{
	/* 获取到该节点所在的链表 */
	List_t *const pxList = pxItemToRemove->pxList;

	/* 如果节点不在链表中则直接返回链表长度 */
	if (pxList == NULL)
	{
		return 0;
	}

	/* 从链表中删除该节点 */
	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

	if (pxList->pxIndex == pxItemToRemove)
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}
	pxItemToRemove->pxList = NULL;
	(pxList->uxNumberOfItems)--;

	return pxList->uxNumberOfItems;
}

/**
 * @brief   遍历链表，并对每个元素执行回调函数。
 * @param   (List_t)          *pxList : 待遍历的链表。
 * @param   (ListPrintCallBack_t) pCallBack : 回调函数指针。
 * @return  (void)
 * @example  打印输出 回调函数示例: vListForEach(xListPerson, &Person_Print);
 * 		void Person_Print(ListItem_t* pxItem)
 * 		{
 * 			Person_t* p = (Person_t*)pxItem->pvContainer; // 将 void* 类型转换为 Person* 类型
 * 			printf("Name: %s, Age: %d\n", p->name, p->age);
 * 		}
 */
void vListForEach(const List_t *const pxList, ListForEachCallBack_t pCallBack)
{

	ListItem_t *pxItem = pxList->xListEnd.pxNext;

	while (pxItem != (ListItem_t *)&(pxList->xListEnd))
	{
		pCallBack(pxItem);
		pxItem = pxItem->pxNext;
	}
}

/**
 * @brief    获取链表长度
 * @param    (List_t) *pxList : 链表
 * @return   (void)
 */
UBaseType_t ulListLength(const List_t *const pxList)
{
	return pxList->uxNumberOfItems;
}
